home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 April
/
EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso
/
EARCD
/
gfx
/
show
/
visagecom.lha
/
VisageCom.e
< prev
next >
Wrap
Text File
|
1996-11-30
|
22KB
|
587 lines
/*************************************************************************
* *
* VisageCom *
* *
* By Philippe "Elwood" FERRUCCI Decines FRANCE *
* *
*************************************************************************/
MODULE 'dos/dos','intuition/screens','intuition/intuition',
'gadtools','libraries/gadtools','reqtools','libraries/reqtools',
'utility/tagitem','graphics/gfxbase',
'graphics/rastport','graphics/text','exec/ports','exec/nodes',
'dos/dosextens','exec/tasks',
'intuition/intuitionbase',
'exec/io', -> iostdreq
'devices/input', -> CMD_WAITEVENT
'devices/inputevent', -> inputevent
'exec/memory' -> MEMF_PUBLIC
ENUM NONE,NOARGS,NOMEM,NOLIB,NOGAD,NOFILE1,NOFILE2
DEF progname[50]:STRING,args:PTR TO LONG,template,rdargs
-> filename can be 108 chars long
DEF filename[108]:STRING,destination[108]:STRING,validdest
DEF p_filelock=NIL,fib=NIL:PTR TO fileinfoblock
DEF topscreen=200 -> horizontal line where the visagecom screen will open
DEF scr=NIL:PTR TO screen,win=NIL:PTR TO window,wintitle[100]:STRING
DEF screen=NIL:PTR TO screen -> screen used only when using 'Set Dir'
DEF visual,glist=NIL,p_gad:PTR TO gadget
DEF idcmp
DEF getout=0,useranswer,p_task:PTR TO task -> to find the visage task
OBJECT button -> used to create a list of button
item:PTR TO CHAR
ENDOBJECT
RAISE NOARGS IF ReadArgs() = NIL, -> automatic error handling :
NOLIB IF OpenLibrary() = NIL, -> when the program is done
NOMEM IF OpenScreenTagList() = NIL, -> I sequentially pick each
NOGAD IF GetVisualInfoA() = NIL, -> potential failure of the
NOGAD IF CreateContext() = NIL, -> program and I build this
NOGAD IF CreateGadgetA() = NIL, -> list.
NOMEM IF OpenWindowTagList() = NIL, -> Thanks to Wouter, the
NOFILE1 IF Read() = -1, -> source is easier to read
NOMEM IF New() = NIL, -> and understand.
NOFILE2 IF AddPart() = NIL,
NOMEM IF RtAllocRequestA() = NIL
PROC main() HANDLE
VOID '$VER: VisageCom 1.22 By Philippe "Elwood" FERRUCCI (28/11/96)'
init()
examinefile(filename)
opengui()
mainloop()
Raise(NONE) -> everything is done we get out of here.
EXCEPT
-> if pointer is still valid then "remove it"
IF p_filelock THEN UnLock(p_filelock)
IF fib THEN FreeDosObject(DOS_FIB,fib)
IF scr THEN ScreenToBack(scr)
IF win THEN CloseWindow(win); win := NIL -> close the window first !
IF glist THEN FreeGadgets(glist) -> and this line second.
IF visual THEN FreeVisualInfo(visual)
IF gadtoolsbase THEN CloseLibrary(gadtoolsbase)
IF reqtoolsbase THEN CloseLibrary(reqtoolsbase)
IF scr THEN CloseScreen(scr); scr := NIL -> those NIL are not
IF screen THEN CloseScreen(screen); screen := NIL -> usefull
-> I close everything before saying Visage to continue to avoid problems
-> I encoutered in double buffering mode
-> (the new selected window wasn't the "in front" one)
-> when Visage is showing an image it (Visage itself or the datatype it
-> is using) locks that file, so before deleting
-> I have to say to Visage to continue in order to remove the lock
IF (getout >= 1) AND (getout <= 5) THEN
IF (p_task := getvisagetask()) THEN Signal(p_task,SIGBREAKF_CTRL_D)
IF (getout = 2) OR (getout = 3)
Delay(50) -> I wait a while to be sure lock is dead
DeleteFile(filename) -> guess what this dos library function do ?
ENDIF
SELECT exception
CASE NOARGS
WriteF('Usage: \s <filename> <destination>\n',progname)
CASE NOMEM
WriteF('Not enough memory !\n')
CASE NOLIB
WriteF('Can''t open required libraries !\n')
CASE NOGAD
WriteF('Failure in a gadtools function !\n')
CASE NOFILE1
WriteF('Can''t read file correctly !\n')
CASE NOFILE2
WriteF('Can''t write file !\n')
ENDSELECT
CleanUp(0) -> Amiga E cleans used RAM
ENDPROC
PROC examinefile(name:PTR TO CHAR)
DEF tmp
IF (p_filelock := Lock(name,ACCESS_READ)) = 0 THEN Raise(NOFILE1)
IF (fib := AllocDosObject(DOS_FIB,NIL))
tmp := Examine(p_filelock,fib)
IF tmp = 0 -> fills 'fib' structure
FreeDosObject(DOS_FIB,fib) -> with infos about the file
fib := NIL
ENDIF
ENDIF
ENDPROC
PROC opengui()
scr := OpenScreenTagList(NIL,[SA_TOP,topscreen, -> open screen at
SA_HEIGHT,50, -> bottom of display
SA_LIKEWORKBENCH,TRUE,
SA_TYPE,PUBLICSCREEN,
SA_PUBNAME,'VisageCom',
SA_DRAGGABLE,FALSE,
-> opened and prepared behind for aesthetic reasons
SA_BEHIND,TRUE,
SA_QUIET,TRUE, -> useless but who cares
TAG_DONE]) -> end of tag list
visual := GetVisualInfoA(scr,NIL) -> initialises some gadtools structures
p_gad := CreateContext({glist}) -> creates the shadow gadget used as
-> the first gadget of the window
-> the same thing is done 6 times (each gadget) so it would be too long
-> and unreadable here. That's why a used a PROC routine.
p_gad:=preparegadget(p_gad,['_Copy','_Delete','_Move','_Rename',
'C_omment','_Set Dir','C_ancel']:button)
-> the window title will be like this: "Choose an action for <filename>"
StrCopy(wintitle,'Image: ',ALL)
StrAdd(wintitle,filename,ALL)
StrAdd(wintitle,' Destination: ',ALL)
StrAdd(wintitle,destination,ALL)
win := OpenWindowTagList(NIL,[WA_TOP,0, -> open a window on the
WA_LEFT,0, -> previous opened screen
WA_WIDTH,640,
WA_PUBSCREEN,scr, -> pointer to the screen
WA_GADGETS,glist, -> gadget list prepared
WA_ACTIVATE, TRUE,
-> I want to be warned by the great Amiga IDCMP system when those
-> events occured: key/mousebutton pressed or window is made inactive or
-> a gadget has been used
WA_IDCMP, IDCMP_VANILLAKEY OR
IDCMP_MOUSEBUTTONS OR
IDCMP_INACTIVEWINDOW OR
IDCMP_INTUITICKS OR
IDCMP_GADGETUP,
WA_TITLE, wintitle,
TAG_DONE])
Gt_RefreshWindow(win,NIL) -> needed by gadtools after window is opened
IF validdest = FALSE THEN disablegad(win,[1,3])
ScreenToFront(scr) -> the screen is ready to be introduced to you
setmouse(scr,p_gad.leftedge,p_gad.topedge) -> mouse goes to last gadget
ENDPROC
PROC mainloop()
DEF int:PTR TO intuitionbase
-> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-> Please pay attention that if you use gadtools features you have to
-> use gadtools version of message managing: GT_GetIMsg and GT_ReplyIMsg
-> instead of the intuition equivalent (GetMsg and ReplyMsg) included in
-> in the E procedure WaitIMessage (have a look at this one in the E doc)
-> used here (I know I'm a bad boy ! )
WHILE getout = 0
idcmp := WaitIMessage(win) -> we wait one of the wanted IDCMP
SELECT idcmp
CASE IDCMP_INTUITICKS
int := intuitionbase
screen := int.firstscreen.nextscreen -> must be the Visage screen
IF StrCmp(screen.title,'Visage') = FALSE THEN getout := -1
CASE IDCMP_GADGETUP -> a gadget has been pressed/released
p_gad := MsgIaddr() -> which one ?
getout := p_gad.gadgetid -> 'getout' is set with the gadget id
CASE IDCMP_MOUSEBUTTONS -> button pressed
-> left mouse button pressed outside the window
IF (MsgCode() = SELECTUP) AND (scr.mousey < 0) THEN getout := -1
CASE IDCMP_INACTIVEWINDOW
ActivateWindow(win) -> makes the window be the active one again
CASE IDCMP_VANILLAKEY -> a key pressed
useranswer := MsgCode() -> which one ?
SELECT useranswer
CASE "c" -> Copy
getout:=1
CASE "d" -> Delete
getout:=2
CASE "m" -> Move
getout:=3
CASE "r" -> Rename
getout:=4
CASE "o" -> Comment
getout:=5
CASE "s" -> Set dir
getout:=6
CASE "a" -> Cancel
getout:=7
ENDSELECT
ENDSELECT
-> Action !!!
SELECT getout -> gadget selected / key pressed
-> please pay attention that all delete actions are made later
-> see below for explanation
CASE 1
copyfile(filename) -> we copy the file to destination
CASE 3
copyfile(filename) -> the same. (delete is done after)
CASE 4
IF (dorename(filename)) = 0 THEN getout := 0 -> rename cancelled
CASE 5
IF (docomment(filename)) = 0 THEN getout := 0 -> comment cancelled
CASE 6
setdir() -> we change destination
StrCopy(wintitle,'Image: ',ALL)
StrAdd(wintitle,filename,ALL)
StrAdd(wintitle,' Destination: ',ALL)
StrAdd(wintitle,destination,ALL)
SetWindowTitles(win,wintitle,-1) -> updates the window title
getout := 0 -> we continue
ENDSELECT
ENDWHILE
ENDPROC
PROC init()
DEF tmplock
-> this is only for writing a good 'Usage' message (if you changed the
-> name of the prog (in 'Vcom' for instance)
IF (GetProgramName(progname,50)) = 1 THEN StrCopy(progname,'VisageCom',ALL)
args:=[NIL,NIL,NIL] -> init args structure.
template:='FILE/A,DEST/A,TOPSCREEN/N' -> 2 arguments needed.
rdargs:=ReadArgs(template,args,NIL) -> dos library function.
StrCopy(filename,args[],ALL) -> copy of args in Estring
StrCopy(destination,args[1],ALL) -> fields.
IF args[2]
topscreen := args[2]
topscreen := ^topscreen
ENDIF
FreeArgs(rdargs) -> dos library function.
-> we check if destination is valid
IF (tmplock := Lock(destination,ACCESS_READ)) = 0
validdest := FALSE
StrCopy(destination,'<Invalid>',ALL)
ELSE
UnLock(tmplock)
validdest := TRUE
ENDIF
gadtoolsbase := OpenLibrary('gadtools.library',39) -> open needed libs
reqtoolsbase := OpenLibrary('reqtools.library',38)
ENDPROC
PROC preparegadget(gad:PTR TO gadget,buttonlist:PTR TO button)
DEF saveptr,id,len,text[100]:STRING
-> next line used to get the default font
DEF p_ta:PTR TO textattr,gfx:PTR TO gfxbase,p_tf:PTR TO textfont,node:PTR TO node
DEF intuilen,intui:PTR TO intuitext
DEF leftedge,between
-> fasten your seat belt and here we go
-> I hope this is the good way to do it
len := ListLen(buttonlist) -> how much gadget we have to create
-> we look for the default font
gfx := gfxbase -> we get a pointer to the gfxbase structure
p_tf := gfx.defaultfont -> in gfxbase we get a pointer to a textfont struct
node := p_tf.message.node -> and another pointer to get the fontname
p_ta := [node.name,p_tf.ysize,p_tf.style,p_tf.flags]:textattr
saveptr := buttonlist
-> here I count how much pixels must be placed between each gadget
FOR id := 1 TO len -> BAD: FOR ind := 1 TO ListLen(buttonlist)
StrAdd(text,^buttonlist) -> we create a string with all texts
buttonlist++ -> we get the next one
ENDFOR
intui := [1,0,RP_JAM1,0,0,p_ta,text,NIL]:intuitext
intuilen := IntuiTextLength(intui) -> length of characters
between := (640 - intuilen) / (len + 1) -> step between each gadget
leftedge := -10 -> a small correction
intuilen := 0
buttonlist := saveptr
FOR id := 1 TO len -> BAD: FOR ind := 1 TO ListLen(buttonlist)
StrCopy(text,^buttonlist,ALL) -> we get the text of the current object
buttonlist++ -> we get the next one for next run
-> this, is to create each gadget at 'between' pixels from the previous
leftedge := leftedge + intuilen + between
-> length of current gadget text
intui := [1,0,RP_JAM1,0,0,p_ta,text,NIL]:intuitext
intuilen := IntuiTextLength(intui)
IF ((id = 1) OR (id = 3)) AND (validdest = FALSE) -> Copy/Move disabled
gad := CreateGadgetA(
BUTTON_KIND,gad, -> type,previous gadget
[leftedge,20,intuilen+15,20, -> leftedge,topedge,width,height
text,p_ta, -> gadgettext,font
id,PLACETEXT_IN, -> ID,position
visual,0]:newgadget, -> visual,userdata
[GT_UNDERSCORE,"_",
GFLG_DISABLED,TRUE,TAG_END]) -> additional taglist
ELSE
gad := CreateGadgetA(
BUTTON_KIND,gad, -> type,previous gadget
[leftedge,20,intuilen+15,20, -> leftedge,topedge,width,height
text,p_ta, -> gadgettext,font
id,PLACETEXT_IN, -> ID,position
visual,0]:newgadget, -> visual,userdata
[GT_UNDERSCORE,"_",TAG_END]) -> additional taglist
ENDIF
ENDFOR
ENDPROC gad
-> enables gadgets of a specific window
PROC enablegad(p_win:PTR TO window,idlist:PTR TO LONG)
DEF len,i,gadid,p_gad:PTR TO gadget
-> instead of saving the gadget address of the 2 gadgets I wanted to
-> enable/disable, I wrote this PROC which allows you to enable the
-> first and the third gadget of a specific window calling:
-> enablegad(win,[1,3])
len := ListLen(idlist)
p_gad := p_win.firstgadget -> we get the address of the first gadget
FOR i := 1 TO len -> for each number of gadget, we lokk for it
gadid := ^idlist; idlist++ -> in the gadget list
WHILE p_gad.gadgetid <> gadid -> of the window
p_gad := p_gad.nextgadget -> and we enable the one
ENDWHILE -> we want: the first one and the
OnGadget(p_gad,p_win,NIL) -> third one here.
ENDFOR
ENDPROC
PROC disablegad(p_win:PTR TO window,idlist:PTR TO LONG)
DEF len,i,gadid,p_gad:PTR TO gadget
len := ListLen(idlist)
p_gad := p_win.firstgadget
FOR i := 1 TO len
gadid := ^idlist; idlist++
WHILE p_gad.gadgetid <> gadid
p_gad := p_gad.nextgadget
ENDWHILE
OffGadget(p_gad,p_win,NIL)
ENDFOR
ENDPROC
PROC copyfile(file)
DEF filelen,filehandler,basename:PTR TO CHAR
DEF mem=NIL
filelen := FileLength(file)
-> file is already locked
IF (filehandler := Open(file,OLDFILE)) = NIL THEN Raise(NOFILE1)
mem := New(filelen) -> we allocate memory to store the file
Read(filehandler,mem,filelen) -> we store the file in memory
Close(filehandler) -> close the file
basename := FilePart(file) -> extract the filename
AddPart(destination,basename,100) -> add this name to destination dir
IF (filehandler := Open(destination,NEWFILE)) = NIL THEN Raise(NOFILE2)
IF Write(filehandler,mem,filelen) = -1 -> error (e.g. no free space)
Close(filehandler)
DeleteFile(destination)
ELSE
Close(filehandler)
-> copy date and filecomment found in 'fib'
IF fib
SetFileDate(destination,fib.datestamp)
SetComment(destination,fib.comment)
FreeDosObject(DOS_FIB,fib); fib := NIL
ENDIF
ENDIF
ENDPROC
PROC dorename(file)
DEF answer[108]:STRING,wintitle[130]:STRING,req
StrCopy(wintitle,'Enter new name for ',ALL)
StrAdd(wintitle,file,ALL)
StrCopy(answer,file,ALL)
req := RtAllocRequestA(RT_REQINFO,NIL) -> allocate what is needed (!)
useranswer := RtGetStringA(answer,200,wintitle,req,
[RT_WINDOW,win,
RT_IDCMPFLAGS,IDCMP_INACTIVEWINDOW,
RTGS_WIDTH,640,
RT_TOPOFFSET,0,
TAG_DONE]) -> taglists should end like this
RtFreeRequest(req) -> free what was allocated
-> if user closed the requester with return/OK then rename file
IF useranswer
-> if you inactive the requester, useranswer will be the IDCMP
IF useranswer = IDCMP_INACTIVEWINDOW
useranswer := 0
ELSE
Rename(file,answer)
ENDIF
ENDIF
ENDPROC useranswer -> used to know if rename has been done or canceled
PROC docomment(file)
DEF req,answer[108]:STRING,wintitle[130]:STRING
StrCopy(wintitle,'Enter comment for ',ALL)
StrAdd(wintitle,file,ALL)
IF fib THEN StrCopy(answer,fib.comment,ALL)
req := RtAllocRequestA(RT_REQINFO,NIL) -> allocate what is needed (!)
useranswer := RtGetStringA(answer,200,wintitle,req,
[RT_WINDOW,win,
RT_IDCMPFLAGS,IDCMP_INACTIVEWINDOW,
RTGS_WIDTH,640,
RT_TOPOFFSET,0,
TAG_DONE]) -> taglists should end like this
RtFreeRequest(req) -> free what was allocated
-> if user closed the requester with return/OK then save comment
IF useranswer
IF useranswer = IDCMP_INACTIVEWINDOW
useranswer := 0
ELSE
SetComment(file,answer)
ENDIF
ENDIF
ENDPROC useranswer -> used to know if setcomment has been done
PROC setdir()
DEF req:PTR TO rtfilerequester,answer[108]:ARRAY
req := RtAllocRequestA(RT_FILEREQ,NIL)
-> as my screen was too small for the requester, here is a second one
screen := OpenScreenTagList(NIL,[SA_LIKEWORKBENCH,TRUE,
SA_TITLE,'Set Dir',
SA_DRAGGABLE,FALSE,
TAG_DONE])
IF validdest THEN RtChangeReqAttrA(req,[RTFI_DIR,destination])
useranswer := RtFileRequestA(req,
answer,'Choose a new destination',
[RT_SCREEN,screen,
RT_REQPOS,REQPOS_CENTERSCR,
RTFI_FLAGS,FREQF_NOFILES,
TAG_DONE])
IF useranswer
validdest := TRUE
StrCopy(destination,req.dir,ALL)
enablegad(win,[1,3])
ENDIF
RtFreeRequest(req)
CloseScreen(screen)
screen := NIL -> this NIL is important (when something fails) !
ENDPROC
PROC getvisagetask()
DEF p_process:PTR TO process,p_cli:PTR TO commandlineinterface
DEF clinum,lastclinum,taskname[80]:STRING,taskfound=FALSE
clinum := 1
lastclinum := MaxCli() -> get the last cli number
-> browse each cli process from 1 to lastclinum - 1
WHILE (taskfound=FALSE) AND (clinum<lastclinum)
p_process := FindCliProc(clinum) -> finds this process
-> perhaps the task has been removed since the call to MaxCli()
IF p_process
p_task := p_process.task -> pointer to the process task
p_cli := Shl(p_process.cli,2) -> converts the BCPL address
taskname := Shl(p_cli.commandname,2) -> commandname is a BCPL too
taskname := TrimStr(taskname) -> needs a correct format
taskname := LowerStr(FilePart(taskname))
IF StrCmp(taskname,'visage',ALL) THEN taskfound := TRUE
ENDIF
INC clinum
ENDWHILE
IF taskfound = FALSE THEN p_task := NIL
ENDPROC p_task
PROC setmouse(scr:PTR TO screen,x,y)
DEF p_iostdreq:PTR TO iostdreq,mp:PTR TO msgport,p_ievent:PTR TO inputevent
DEF ppix:PTR TO iepointerpixel
-> code based upon SetMouse from Ketil Hunn
IF (mp := CreateMsgPort())
IF (p_ievent := AllocVec(SIZEOF inputevent, MEMF_PUBLIC))
IF (ppix := AllocVec(SIZEOF iepointerpixel, MEMF_PUBLIC))
IF p_iostdreq := CreateIORequest(mp,SIZEOF iostdreq)
IF Not (OpenDevice('input.device', NIL, p_iostdreq, NIL))
ppix.screen := scr
ppix.positionx := x
ppix.positiony := y
p_ievent.nextevent := NIL
p_ievent.class := IECLASS_NEWPOINTERPOS
p_ievent.subclass := IESUBCLASS_PIXEL
p_ievent.code := 0
p_ievent.qualifier := NIL
p_ievent.eventaddress := ppix
p_iostdreq.data := p_ievent
p_iostdreq.length := SIZEOF inputevent
p_iostdreq.command := IND_WRITEEVENT
DoIO(p_iostdreq)
CloseDevice(p_iostdreq)
ENDIF
DeleteIORequest(p_iostdreq)
ENDIF
FreeVec(ppix)
ENDIF
FreeVec(p_ievent)
ENDIF
DeleteMsgPort(mp)
ENDIF
ENDPROC